package ai.people.netmon.gateway.exception;

import ai.people.netmon.framework.exception.enums.CommonEnum;
import ai.people.netmon.framework.exception.type.CustomizeRuntimeException;
import ai.people.netmon.framework.model.response.Result;
import ai.people.netmon.framework.utils.ResultUtil;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 全局错误异常处理程序
 *
 * @author yuanqinglong
 * @date 2022/2/17 13:58
 */
@Order(-1)
@Component
public class GlobalErrorExceptionHandler implements ErrorWebExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(GlobalErrorExceptionHandler.class);

    @Autowired
    private LoadBalancerClient loadBalancerClient;
    /**
     * 处理
     *
     * @param exchange 交换
     * @param ex       异常
     * @return {@link Mono}<{@link Void}>
     */
    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        ServiceInstance choose = loadBalancerClient.choose("NM-SERVICE-SIGNAL");
        ServerHttpResponse response = exchange.getResponse();
        // 设置返回JSON
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        if (response.isCommitted()) {
            return Mono.error(ex);
        }
        Result<Object> errorResult = ResultUtil.error(CommonEnum.SERVER_ERROR);
        if (ex instanceof ResponseStatusException && ((ResponseStatusException) ex).getStatus() == HttpStatus.NOT_FOUND) {
            errorResult = ResultUtil.error(CommonEnum.ACCESS_SERVICE_DOES_NOT_EXIST);
        } else if (ex instanceof CustomizeRuntimeException) {
            errorResult = ResultUtil.error((CustomizeRuntimeException) ex);
        } else if (ex instanceof NotFoundException) {
            errorResult = ResultUtil.error(CommonEnum.SERVICE_IS_STARTING);
        }
        logger.error("gateway exception {}:", errorResult, ex);
        byte[] finalDataBuffer = JSONObject.toJSONString(errorResult).getBytes();
        return response.writeWith(Mono.fromSupplier(() -> response.bufferFactory().wrap(finalDataBuffer)));
    }
}
